package com.damacheng009.future.alarm.service;

import java.util.Date;
import java.util.List;

import org.nutz.dao.Dao;
import org.ta4j.core.BaseTimeSeries;
import org.ta4j.core.TimeSeries;
import org.ta4j.core.indicators.EMAIndicator;
import org.ta4j.core.indicators.MACDIndicator;
import org.ta4j.core.indicators.SMAIndicator;
import org.ta4j.core.indicators.helpers.ClosePriceIndicator;
import org.ta4j.core.indicators.statistics.SimpleLinearRegressionIndicator;
import org.ta4j.core.num.Num;
import org.ta4j.core.num.PrecisionNum;

import com.damacheng009.future.alarm.crawler.SinaRealtimeCrawler;
import com.damacheng009.future.alarm.domain.TKLine;
import com.damacheng009.future.alarm.toolkit.DaoTool;
import com.damacheng009.future.alarm.toolkit.GlobalConfig;
import com.damacheng009.future.alarm.toolkit.MiscTool;
import com.damacheng009.future.alarm.vo.KLineVo;
import com.damacheng009.future.alarm.vo.DayKLineInfo;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;

public class DayKLineService {

	/**
	 * 得到N日的SMA的值
	 * @param code
	 * @param days
	 * @return
	 */
	public static DayKLineInfo calculate(String code, int days) {
		if (code.startsWith("JO")) {
			code = GlobalConfig.cngold2Sina.get(code);
		}
		
		DayKLineInfo smaInfo = new DayKLineInfo();
		Dao dao = DaoTool.createDao(code);
		List<TKLine> klines = dao.query(TKLine.class, null);
		
		// 数据库的数据并一定是包括当天的，可能需要实时数据
		TKLine lastLine = klines.get(klines.size() - 1);
		
		SinaRealtimeCrawler realtimeCrawler = new SinaRealtimeCrawler();
		KLineVo nowVo = realtimeCrawler.getKLine(code);
		
		Float nowClosePrice = Float.parseFloat(nowVo.getC());
		
		if (NumberUtil.compare(nowClosePrice, lastLine.getClose()) != 0 
				|| !lastLine.getDate().equals(DateUtil.today())) {
			TKLine line = new TKLine();
			line.setDate(DateUtil.offsetDay(new Date(), 1).toDateStr());
			line.setClose(Float.parseFloat(nowVo.getC()));
			line.setHigh(Float.parseFloat(nowVo.getH()));
			line.setLow(Float.parseFloat(nowVo.getL()));
			line.setOpen(Float.parseFloat(nowVo.getO()));
			
			if (nowVo.getP() != null) {
				line.setOpid((int)Float.parseFloat(nowVo.getP()));
			}
			
			line.setVolume((int)Float.parseFloat(nowVo.getV()));
			klines.add(line);
		}
		
		TimeSeries series = new BaseTimeSeries.SeriesBuilder().withName("oneday_series").build();

		for (TKLine line : klines) {
			// 如果当前K线的结束时间跟上一跟相同则跳过
			if (!series.isEmpty() && MiscTool.changeShanghaiToUTC(line.getDate() + " 00:00:00").isEqual(series.getLastBar().getEndTime())) {
				continue;
			}
			
			series.addBar(MiscTool.changeShanghaiToUTC(line.getDate() + " 00:00:00"), line.getOpen(), 
					line.getHigh(), line.getLow(), line.getClose(), line.getVolume());
		}
		
		int endIndex = series.getEndIndex();
		
		ClosePriceIndicator closePriceIndicator = new ClosePriceIndicator(series);
		
		SMAIndicator sma55Indicator = new SMAIndicator(closePriceIndicator, days);
		
		smaInfo.setSmaValue(sma55Indicator.getValue(endIndex));
	
		Num diff = PrecisionNum.valueOf(nowClosePrice).minus(smaInfo.getSmaValue()).abs();
		smaInfo.setDiff(diff);
		
		// 计算偏离度
		Num pianlidu = diff.dividedBy(smaInfo.getSmaValue());
		smaInfo.setPianlidu(pianlidu);
		
		// 计算斜率
		SimpleLinearRegressionIndicator sma55LRIndicator = 
				new SimpleLinearRegressionIndicator(sma55Indicator, 5, SimpleLinearRegressionIndicator.SimpleLinearRegressionType.slope);
		
		smaInfo.setSlope55(sma55LRIndicator.getValue(endIndex));
		
		MACDIndicator macdDiffIndicator = new MACDIndicator(closePriceIndicator, 6, 30);
		EMAIndicator macdDeaIndicator = new EMAIndicator(macdDiffIndicator, 6);
		
		smaInfo.setMacdDiff(macdDiffIndicator.getValue(endIndex));
		smaInfo.setMacdDea(macdDeaIndicator.getValue(endIndex));
		smaInfo.setMacdValue(smaInfo.getMacdDiff().minus(smaInfo.getMacdDea()).multipliedBy(PrecisionNum.valueOf(2)));
		
		return smaInfo;
	}

}
